package com.heima.comment.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.heima.comment.dto.CommentDto;
import com.heima.comment.dto.CommentLikeDto;
import com.heima.comment.dto.CommentSaveDto;
import com.heima.comment.entity.ApComment;
import com.heima.comment.entity.ApCommentLike;
import com.heima.comment.entity.ApUser;
import com.heima.comment.feign.UserFeign;
import com.heima.comment.service.ICommentService;
import com.heima.comment.vo.ApCommentVo;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.util.UserThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CommentServiceImpl implements ICommentService {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UserFeign userFeign;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private GreenTextScan greenTextScan;

    /**
     * 发表评论-保存
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        // 接收参数判断
        if (dto==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 用户登录判断，浏览亦可访问与评论
        User user = UserThreadLocalUtil.get();
        if (user==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 新增，注意添加限制：评论内容要求不大于140字
        if (dto.getContent().length()>140) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 阿里云文本审核
        boolean isPass = true;
        isPass = checkText(dto.getContent());
        if (!isPass) return ResponseResult.errorResult(404,"评论含有敏感词，请重新编辑！");

        // MongoDB存储新增评论
        // 创建评论对象，判断并初始化
        ApComment apComment = new ApComment();
        // apComment.setId("");
        if (user.getUserId()==0) {
            // 用户仅浏览，以游客身份登录
            apComment.setUserId(0);
            apComment.setUserName("游客");
            apComment.setImage("");
        }else {
            // 远程调用查询用户信息
            ResponseResult<ApUser> result = userFeign.getUserById(user.getUserId());
            ApUser apUser = result.getData();
            apComment.setUserId(user.getUserId());
            apComment.setUserName(apUser.getName());
            apComment.setImage(apUser.getImage());
        }
        apComment.setArticleId(dto.getArticleId());
        apComment.setContent(dto.getContent());
        apComment.setLikes(0);
        apComment.setRepay(0);
        apComment.setCreatedTime(new Date());
        // MongoDB存储新增评论
        mongoTemplate.save(apComment);
        // 返回结果集
        return ResponseResult.okResult();
    }

    /**
     * aliyun自动审核文本
     * @param content
     * @return
     */
    private boolean checkText(String content) {
        boolean isPass = false;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                // suggestion
                // pass：文本正常，可以直接放行。
                // review：文本需要进一步人工审核。             label=porn
                // block：文本违规，可以直接删除或者限制公开。  label=porn
                case "pass":
                    isPass = true;
                    break;
                case "review":
                    log.info("[阿里云文本审核未通过，需要人工审核，原因是：{}]",map.get("label"));
                    isPass = false;
                    break;
                case "block":
                    log.info("[阿里云文本审核未通过，需要人工审核，原因是：{}]",map.get("label"));
                    isPass = false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isPass;
    }

    /**
     * 评论列表展示
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(CommentDto dto) {
        // 判断登录人
        User user = UserThreadLocalUtil.get();
        if (user==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 页码大小设定，添加笔记
        Integer size = dto.getSize();
        if (size==null||size<=0||size>=50) {
            dto.setSize(10);
        }

        // 条件构造器
        // 1.拼接 2.拆分
        // Query query = new Query(Criteria.where("articleId").is(dto.getArticleId().and("createdTime").lt(dto.getMinDate()));
        Query query = new Query();
        // 文章id以及评论时间
        query.addCriteria(Criteria.where("articleId").is(dto.getArticleId()));
        query.addCriteria(Criteria.where("createdTime").lt(dto.getMinDate()));
        // 分页
        query.limit(dto.getSize());
        // 按照评论时间排序
        query.with(Sort.by(Sort.Direction.DESC,"createdTime"));
        // 写法二：分页与评论时间排序
        /*Pageable page = PageRequest.of(0, dto.getSize(), Sort.Direction.DESC, "createdTime");
        query.with(page);*/
        // 查询
        List<ApComment> apComments = mongoTemplate.find(query, ApComment.class);

        // 避免同一人重复点赞，查看当前列表是否已有自己点赞信息
        // Redis：提高效率，记录当前登录人是否对该文章点赞
        List<ApCommentVo> apCommentVoList = new ArrayList<>();
        for (ApComment apComment : apComments) {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment,apCommentVo);
            Boolean hasKey = redisTemplate.hasKey("comment_like_" + user.getUserId() + "_" + apComment.getId());
            apCommentVo.setOperation(hasKey?0:1);
            apCommentVoList.add(apCommentVo);
        }

        return ResponseResult.okResult(apCommentVoList);
    }

    /**
     * 评论点赞
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        // 评论点赞：0点赞，1取消点赞
        // 接收参数判断
        if (dto==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 当前用户判断，此处可添加条件非登录用户不能点赞
        User user = UserThreadLocalUtil.get();
        if (user==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        // 评论点赞或取消点赞记录数据操作
        // 思路：1.记录点赞记录 2.修改点赞数
        // 方案一：增删，不全部记录；方案二：只增不删，记录所有数据

        // 方案一：增删，不全部记录
        if (dto.getOperation()==0) {
            // 点赞：1.添加点赞数据 2.修改点赞数
            // 添加点赞数据
            ApCommentLike apCommentLike = new ApCommentLike();
            // apCommentLike.setId("");
            apCommentLike.setUserId(user.getUserId());
            apCommentLike.setCommentId(dto.getCommentId());
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.save(apCommentLike);
            // 修改点赞数
            Query query = new Query(Criteria.where("_id").is(dto.getCommentId()));
            Update update = new Update();
            update.inc("likes",1);
            mongoTemplate.updateFirst(query,update,ApComment.class);

            // 登陆人操作记录在Redis中，列表展示时进行判断
            // 只需要判断是否存在key即可，set后值可任意
            redisTemplate.boundValueOps("comment_like_"+user.getUserId()+"_"+dto.getCommentId()).set("");
        }else {
            // 取消点赞：1.删除点赞数据 2.修改点赞数
            // 删除点赞数据
            mongoTemplate.remove(new Query(Criteria.where("userId").is(user.getUserId()).and("commentId").is(dto.getCommentId())),ApCommentLike.class);

            // 修改点赞数
            Query query = new Query(Criteria.where("_id").is(dto.getCommentId()));
            Update update = new Update();
            update.inc("likes",-1);
            mongoTemplate.updateFirst(query,update,ApComment.class);

            // 登陆人操作记录在Redis中，列表展示时进行判断
            // 只需要判断是否存在key即可，set后值可任意
            redisTemplate.delete("comment_like_"+user.getUserId()+"_"+dto.getCommentId());
        }

        // 方案二：只增不删，记录所有数据
        /*ApCommentLike apCommentLike = new ApCommentLike();
        apCommentLike.setUserId(user.getUserId());
        apCommentLike.setCommentId(dto.getCommentId());
        apCommentLike.setOperation(dto.getOperation());
        mongoTemplate.save(apCommentLike);
        Query query = new Query(Criteria.where("_id").is(dto.getCommentId()));
        Update update = new Update();
        if (dto.getOperation()==0) {
            update.inc("likes",1);
            mongoTemplate.updateFirst(query,update,ApComment.class);
        }else {
            update.inc("likes",-1);
            mongoTemplate.updateFirst(query,update,ApComment.class);
        }*/

        return ResponseResult.okResult();
    }
}
